package com.tavio.vaultboy.element;

import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;

import com.tavio.vaultboy.element.state.GravityState;
import com.tavio.vaultboy.element.type.ElementType;
import com.tavio.vaultboy.scene.SceneManager;

public class VaultBoy extends SpriteElement{
	
	private Element collidedY = null;
	
	private Element collidedX = null;
	
	public Box boxBeingGrabbed = null;
	
	private float controlValueX = 0;
	
	private float oldX = 0;
	
	private float controlValueY = 0;
	
	private float controlValueGrab = 0;
	
	public VaultBoy(float x, float y, float width, float height,
			float acceleration, TiledTextureRegion tiledTextureRegion, VertexBufferObjectManager vertexBufferObjectManager) {
		super(ElementType.VAULT_BOY, x, y, width, height, acceleration, tiledTextureRegion, vertexBufferObjectManager);
	}

	
	public void updatePositionAndCheckCollisions(float timeElapsed) {
		// Get the values of the controllers
		controlValueX = SceneManager.getInstance().activeMovementController.controlValue;
		controlValueY = SceneManager.getInstance().activeJumpController.controlValue;
		controlValueGrab = SceneManager.getInstance().activeGrabController.controlValue;
		
		// Update the velocities on axes Y and X
		velocityX = controlValueX * 7.5f;
		velocityY += acceleration * accelerationModifier * timeElapsed;
		
		// Jump
		if(controlValueY == 1 && !jumping) { 
			velocityY -= 7.5 * accelerationModifier;
			jumping = true;
		}
		
		// Limit velocity on Y
		if(velocityY > 10)
			velocityY = 10;
		
		// Update player position on Y
		y += velocityY;
		getBoundingBox().update();
		
		//Check for collision with elements on Y
		for(Element element : SceneManager.getInstance().collidableElements) {
			if(getBoundingBox().collidesWith(element.getBoundingBox()) && 
					! this.equals(element)) {
				collidedY = element;
				// Move back the object
				y -= velocityY;
				getBoundingBox().update();
				velocityY = 0;	
				
				// Now move it again so it touches the element it would have collided with  
				
				if(GravityState.DOWN.equals(SceneManager.getInstance().gravityState)) {
					if(collidedY.getBoundingBox().top >= getBoundingBox().bottom) {
						y = collidedY.getBoundingBox().top - getSprite().getHeight();
						if(jumping) // If the object was jumping, it has now reached the floor with its "feet" and is not jumping anymore
							jumping = false;
					}
					else // The object hit the ceiling with his "head", he is still jumping
						y = collidedY.getBoundingBox().bottom;
					
				} else {
					if(collidedY.getBoundingBox().bottom <= getBoundingBox().top) {
						y = collidedY.getBoundingBox().bottom;
						if(jumping)
							jumping = false;
					}
					else
						y = collidedY.getBoundingBox().top - getSprite().getHeight();
				}
				
				break;
			}
		}
		
		
		oldX = x;
		
		// Bellow we check if the player is trying to grab an object
		if(controlValueGrab == 0) {
			if(boxBeingGrabbed != null)
				boxBeingGrabbed.pushMovement = 0;
			boxBeingGrabbed = null;
		}
		else if(!jumping && boxBeingGrabbed == null) { 
			// The player is holding the grab button but no object is being held yet
			
			// We move the player's bounding box left and then right in search of an object to grab
			x += 1;
			getBoundingBox().update();
			
			for(Box box : SceneManager.getInstance().boxes) {
				if(getBoundingBox().collidesWith(box.getBoundingBox())) {
					boxBeingGrabbed = box;
					break;
				}
			}
			
			if(boxBeingGrabbed == null) {
				x -= 2;
				getBoundingBox().update();
				
				for(Box box : SceneManager.getInstance().boxes) {
					if(getBoundingBox().collidesWith(box.getBoundingBox())) {
						boxBeingGrabbed = box;
						break;
					}
				}
			}
		} 
		
			
		x = oldX;
		
		// If the player is moving in the X axis, check for collision in the X axis
		if(velocityX != 0)
		{
			// Update player position on X 
			x += velocityX;
			getBoundingBox().update();
			
			//Check for collision with elements on X
			for(Element element : SceneManager.getInstance().collidableElements) {
				if(getBoundingBox().collidesWith(element.getBoundingBox()) && 
						! this.equals(element)) {
					collidedX = element;	
					// Move back the object
					x -= velocityX;
					getBoundingBox().update();
					velocityX = 0;	
					
					// Now move it again so it touches the element it would have collided with
					
					if(collidedX.getBoundingBox().left >= getBoundingBox().right)   //Element is on the right
						x = collidedX.getBoundingBox().left - getSprite().getWidth();
					
					else   //Element is on the left 
						x = collidedX.getBoundingBox().right;
					break;
				}
			}

			// The player is moving, let's move any object he is grabbing
			if(boxBeingGrabbed != null) 
				boxBeingGrabbed.pushMovement = (controlValueX > 0) ? 1 : -1;	
		} else if (boxBeingGrabbed != null)
			// The player is not moving, let' stop any objects he is grabbing  
			boxBeingGrabbed.pushMovement = 0;
		
		getSprite().setPosition(x, y);
		getBoundingBox().update();
		
		if(collidedY == null) {
			jumping = true;
		}
		
		collidedY = null;
		collidedX = null;
		
		
	}


}
